package com.zzl.bonds.ticket.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzl.bonds.ticket.constant.*;
import com.zzl.bonds.ticket.constant.status.*;
import com.zzl.bonds.ticket.constant.type.*;
import com.zzl.bonds.ticket.dao.TicketransferDao;
import com.zzl.bonds.ticket.dto.*;
import com.zzl.bonds.ticket.dto.KeyValue;
import com.zzl.bonds.ticket.dto.common.MsgInfoDto;
import com.zzl.bonds.ticket.dto.feign.ApprovalSubmitDto;
import com.zzl.bonds.ticket.dto.feign.NoticeApprovalResult;
import com.zzl.bonds.ticket.dto.feign.TicketContractListDto;
import com.zzl.bonds.ticket.entity.*;
import com.zzl.bonds.ticket.feign.BaseDataFeign;
import com.zzl.bonds.ticket.feign.ContractFeign;
import com.zzl.bonds.ticket.feign.ProcessFeign;
import com.zzl.bonds.ticket.feign.UserFeign;
import com.zzl.bonds.ticket.manager.SendMessageManager;
import com.zzl.bonds.ticket.manager.TicketManager;
import com.zzl.bonds.ticket.service.*;
import com.zzl.bonds.ticket.service.common.SendMsgService;
import com.zzl.bonds.ticket.untils.DateUtils;
import com.zzl.bonds.ticket.untils.NumberToCN;
import com.zzl.bonds.ticket.untils.StrUtils;
import com.zzl.bonds.ticket.untils.TicketNoUtils;
import com.zzl.general.common.constant.Constant;
import com.zzl.general.common.exception.SysException;
import com.zzl.general.common.requestparameter.StringIds;
import com.zzl.general.common.serurity.entity.User;
import com.zzl.general.common.utils.*;
import com.zzl.sharding.user.dto.UserDto;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.Arrays.asList;

/**
 * 转让申请单
 *
 * @author sunpp
 * @date 2022-02-16 11:14:07
 */
@Service("ticketTransferService")
public class TicketTransferServiceImpl extends ServiceImpl<TicketransferDao, TicketransferEntity> implements TicketTransferService {

    @Autowired
    private TicketService ticketService;

    @Autowired
    private TicketOperateLogService ticketOperateLogService;

    @Autowired
    private SignatureInformationService signatureInformationService;

    @Autowired
    private TicketDataService ticketDataService;

    @Autowired
    private TicketFinanceService ticketFinanceService;

    @Autowired
    private TicketManager ticketManager;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private TicketOpenService ticketOpenService;


    @Autowired
    private SendMessageManager sendMessageManager;
    @Autowired
    private ContractFeign contractFeign;

    @Autowired
    private TicketCirculationEnterpriseService ticketCirculationEnterpriseService;

    @Autowired
    private TicketProcessService ticketProcessService;
    @Autowired
    private ProcessFeign processFeign;

    @Autowired
    private UserFeign userFeign;
    @Autowired
    private SendMsgService sendMsgService;
    @Autowired
    private TicketFlowChartService ticketFlowChartService;
    @Autowired
    private BusinessContractService businessContractService;
    @Autowired
    private BaseDataFeign baseDataFeign;
    /**
     * 分页查询
     *
     * @param params 查询参数
     * @param type   1为待复核 2为待平台审批，3为待签收
     * @return 分页数据
     */
    @Override
    public PageUtils queryPage(Map<String, Object> params, User user, String type) {
        String handStatusStr = (String) params.get("handStatus");
        if (StringUtils.isNotBlank(handStatusStr)) {
            Integer handStatus = Integer.parseInt(handStatusStr);
            List<Integer> ticketStatusList = null;
            if (HandStatusEnum.OPEN_ING.getCode().equals(handStatus)) {
                ticketStatusList = TicketStatusEnum.TRANSFER_IN_LIST;
            } else if (HandStatusEnum.SUCCESS.getCode().equals(handStatus)) {
                ticketStatusList = TicketStatusEnum.SUCCESS_IN_LIST;
            } else if (HandStatusEnum.FAIL.getCode().equals(handStatus)) {
                ticketStatusList = TicketStatusEnum.REJECT_LIST;
            }
            params.put("ticketStatusList", ticketStatusList);
        }
        //排序字段：create_time
        String pageField = (String) params.get(Constant.PAGE);
        //排序方式 order:  desc asc
        String order = (String) params.get(Constant.ORDER);
        IPage<TicketTransferPage> page = new Query<TicketTransferPage>()
                .getPage(params, StringUtils.isBlank(pageField)
                        ? StringConstant.CREATE_TIME_FILED : pageField, Constant.ASC.equals(order));
//        if("1".equals(type)){
//            //查看有复核权限的转让申请
//            JSONObject processParams=new JSONObject();
//            processParams.put("userId",user.getId());
//            processParams.put("approveTypeCode",ApproveTypeEnum.TRANSFER.getCode());
//            List<String> transferIds=processFeign.getByReviewer(processParams);
//            if(CollectionUtils.isEmpty(transferIds)){
//                return new PageUtils(page);
//            }
//            params.put("ids",transferIds);
//        }
        IPage<TicketTransferPage> transferPage = this.baseMapper.queryPage(page, params);
        List<TicketTransferPage> pageRecords = transferPage.getRecords();
        if (!CollectionUtils.isEmpty(pageRecords)) {
            this.improveEchoInfo(pageRecords, type);
        }
        return new PageUtils(page);
    }

    private void improveEchoInfo(List<TicketTransferPage> pageRecords, String type) {
        KeyValue keyValue = new KeyValue();
        keyValue.setValue(KeyTypeEnum.getValue(type));
        for (TicketTransferPage pageRecord : pageRecords) {
            if (type.equals(KeyTypeEnum.KEY_TYPE_DETAILS.getCode())) {
                pageRecord.setHandStatusInfo(TicketStatusEnum.getStatusHandInfo(pageRecord.getTicketStatus()));
                if (TicketStatusEnum.REJECT_LIST.contains(pageRecord.getTicketStatus()) || TicketStatusEnum.CANCEL.getCode().equals(pageRecord.getTicketStatus())) {
                    pageRecord.setHandStatus("失败");
                    KeyValue record = new KeyValue();
                    record.setKey(pageRecord.getTicketStatus());
                    record.setValue("重新申请");
                    pageRecord.setOperateButton(asList(keyValue, record));
                } else if (TicketStatusEnum.TRANSFER_IN_LIST.contains(pageRecord.getTicketStatus())) {
                    pageRecord.setHandStatus("转让中");
                    KeyValue record = new KeyValue();
                    record.setKey(pageRecord.getTicketStatus());
                    if(TicketStatusEnum.TRANSFER_PENDING_REVIEW.getCode().equals(pageRecord.getTicketStatus())){
                        record.setValue("撤销转单");
                    }
                    pageRecord.setOperateButton(asList(keyValue, record));
                } else if (TicketStatusEnum.SUCCESS_IN_LIST.contains(pageRecord.getTicketStatus())) {
                    pageRecord.setHandStatus("成功");
                    pageRecord.setOperateButton(Collections.singletonList(keyValue));
                }
            } else {
                pageRecord.setOperateButton(Collections.singletonList(keyValue));
            }
            pageRecord.setHandProgress(TicketStatusEnum.getProgress(pageRecord.getTicketStatus()));
        }
    }

    @Override
    public PageUtils listSignApprove(Map<String, Object> params, User user) {
        return this.queryPage(params, user, "3");
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void cancelTransferTicket(String id, User user) throws SysException {
        TicketransferEntity ticketransferEntity = this.getById(id);
        if (!TicketStatusEnum.TRANSFER_PENDING_REVIEW.getCode().equals(ticketransferEntity.getTicketStatus())) {
            throw new SysException("该票不在内部复核中不可被撤销！");
        }
        ticketransferEntity.setTicketStatus(TicketStatusEnum.CANCEL.getCode());
        //更新子票和留存票及母票数据
        List<String> ticketIds = new ArrayList<>();
        ticketIds.add(ticketransferEntity.getParentTicketId());
        ticketIds.add(ticketransferEntity.getTicketId());
        if (StringUtils.isNotBlank(ticketransferEntity.getTicketRetentionId())) {
            ticketIds.add(ticketransferEntity.getTicketRetentionId());
        }
        List<TicketEntity> ticketEntities = new ArrayList<>(ticketService.listByIds(ticketIds));
        for (TicketEntity e : ticketEntities) {
            if (e.getId().equals(ticketransferEntity.getParentTicketId())) {
                e.setInvalidReason(InvalidReasonEnum.TICKET_TRANSFER_FAIL.getCode());
                e.setTicketStatus(TicketStatusEnum.NORMAL_HOLDING.getCode());
                //票据金额
                e.setTicketAvailableAmount(add(e.getTicketAvailableAmount(), ticketransferEntity.getTransferAmount()));
                //转让中冻结金额
                e.setTransferFrozenAmount(sub(e.getTransferFrozenAmount(), ticketransferEntity.getTransferAmount()));
            } else {
                e.setInvalidReason(InvalidReasonEnum.TRANSFER_TICKET_CANCEL.getCode());
                e.setTicketStatus(TicketStatusEnum.INVALID.getCode());
            }
        }
        baseMapper.updateById(ticketransferEntity);
        ticketService.updateBatchById(ticketEntities);
        //保存撤回操作记录
        this.saveCancelOperateLog(ticketransferEntity, user);
        //保存票据流转图
        this.cancelTransferFlowChart(ticketransferEntity, user);
        //发送撤回消息
        this.sendCancelMessage(ticketransferEntity, user);
    }

    private void sendCancelMessage(TicketransferEntity ticketransferEntity, User user) throws SysException {
        QueryWrapper<TicketProcessEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TicketProcessEntity::getTicketTransferId, ticketransferEntity.getId())
                .eq(TicketProcessEntity::getApproveType, ApproveTypeEnum.TRANSFER.getCode());
        TicketProcessEntity ticketProcessEntity = ticketProcessService.getOne(queryWrapper);
        //获取要发送用户的ids
        List<String> allAuditUserIds = processFeign.getAllAuditUserIds(ticketProcessEntity.getApproveId());

        //给复核人员发送消息
        String msg = MailMessageConstant.TICKET_TRANSFER_WITHDRAW_MSG.replace(MailMessageConstant.TICKET_REPLACE_SIGN, ticketransferEntity.getReceiveEnterpriseName())
                .replace(MailMessageConstant.TICKET_REPLACE_MONEY, NumberUtil.numberFormatString(ticketransferEntity.getTransferAmount()));
        sendMsgService.sendMsgToAllNotifierWithBtnName(ticketransferEntity.getId(), allAuditUserIds
                , GotoTypeEnum.GOTO_TYPE_TRANSFER.getCode().toString(), msg, user, null, "查看");

    }

    private void saveCancelOperateLog(TicketransferEntity ticketransferEntity, User user) {
        //添加日志
        List<TicketOperateLogEntity> adds = new ArrayList<>();
        TicketOperateLogEntity ticketOperateLogEntity = ticketOperateLogService.getTicketOperateLogEntity(LogActionTypeEnum.TICKET_TYPE_TRANSFER.getCode(), ticketransferEntity.getId()
                , TicketLogStatusEnum.TRANSFER_PENDING_REVIEW.getCode(), OperateLogTypeEnum.WITHDRAW.getCode(), TicketLogStatusEnum.INVALID.getCode(), user
                , "",
                ticketransferEntity.getReceiveEnterpriseId(), ticketransferEntity.getReceiveEnterpriseName(),
                ticketransferEntity.getTransferEnterpriseId(), ticketransferEntity.getTransferEnterpriseName(), ticketransferEntity.getTicketId(), "0", null, null);
        TicketOperateLogEntity parentLog = ticketOperateLogService.getTicketOperateLogEntity(LogActionTypeEnum.TICKET_TYPE_TRANSFER.getCode(), ticketransferEntity.getId()
                , TicketLogStatusEnum.INVALID.getCode(), OperateLogTypeEnum.WITHDRAW.getCode(), TicketLogStatusEnum.TRANSFER_SUCCESS.getCode(), user
                , "",
                ticketransferEntity.getReceiveEnterpriseId(), ticketransferEntity.getReceiveEnterpriseName(),
                ticketransferEntity.getTransferEnterpriseId(), ticketransferEntity.getTransferEnterpriseName(), ticketransferEntity.getParentTicketId(), "1", null, null);
        if (StringUtils.isNotBlank(ticketransferEntity.getTicketRetentionId())) {
            TicketOperateLogEntity childLog = ticketOperateLogService.getTicketOperateLogEntity(LogActionTypeEnum.TICKET_TYPE_TRANSFER.getCode(), ticketransferEntity.getId()
                    , TicketLogStatusEnum.TRANSFER_RETAINED.getCode(), OperateLogTypeEnum.WITHDRAW.getCode(), TicketLogStatusEnum.INVALID.getCode(), user
                    , "",
                    ticketransferEntity.getReceiveEnterpriseId(), ticketransferEntity.getReceiveEnterpriseName(),
                    ticketransferEntity.getTransferEnterpriseId(), ticketransferEntity.getTransferEnterpriseName(), ticketransferEntity.getTicketRetentionId(), "1", null, null);
            adds.add(childLog);
        }
        adds.add(ticketOperateLogEntity);
        adds.add(parentLog);
        ticketOperateLogService.saveBatch(adds);
    }

    private void cancelTransferFlowChart(TicketransferEntity ticketTransferEntity, User user) throws SysException {
        List<String> ticketIds = new ArrayList<>();
        ticketIds.add(ticketTransferEntity.getTicketId());
        ticketIds.add(ticketTransferEntity.getParentTicketId());
        if (StringUtils.isNotBlank(ticketTransferEntity.getTicketRetentionId())) {
            ticketIds.add(ticketTransferEntity.getTicketRetentionId());
        }
        List<TicketFlowChartEntity> chartEntities = ticketFlowChartService.listByTicketIds(ticketIds);
        chartEntities.forEach(e -> {
            if (e.getTicketId().equals(ticketTransferEntity.getParentTicketId())) {
                e.setTicketStatus("0");
            } else {
                e.setTicketStatus("3");
            }
        });
        if (!ticketFlowChartService.updateBatchById(chartEntities)) {
            throw new SysException("撤回修改失败！");
        }
    }

    private void passTransferFlowChart(TicketransferEntity ticketTransferEntity, User user) throws SysException {
        List<String> ticketIds = new ArrayList<>();
        ticketIds.add(ticketTransferEntity.getTicketId());
        ticketIds.add(ticketTransferEntity.getParentTicketId());
        if (StringUtils.isNotBlank(ticketTransferEntity.getTicketRetentionId())) {
            ticketIds.add(ticketTransferEntity.getTicketRetentionId());
        }
        List<TicketFlowChartEntity> chartEntities = ticketFlowChartService.listByTicketIds(ticketIds);
        chartEntities.forEach(e -> {
            if (e.getTicketId().equals(ticketTransferEntity.getParentTicketId())) {
                e.setTicketStatus("0");
            } else {
                e.setTicketStatus("1");
            }
        });
        if (!ticketFlowChartService.updateBatchById(chartEntities)) {
            throw new SysException("撤回修改失败！");
        }
    }

    @Override
    public StatisticsDataDto getTransferSignData(User user) {

        return baseMapper.getTransferSignData(user.getEnterpriseId());
    }

    @Override
    public void executeWaitingPayment(Integer days) {
        List<TicketransferEntity> list = getAdvanceTransferTicket(days);
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        //处理申请单
        list.forEach(e -> e.setTicketStatus(TicketStatusEnum.WAITING_PAYMENT.getCode()));
        this.updateBatchById(list);
        //处理票据
        List<String> parentIds = new ArrayList<>();
        List<String> ticketRetentionIds = new ArrayList<>();
        List<String> ticketIds = new ArrayList<>();
        for (TicketransferEntity ticketransferEntity : list) {
            parentIds.add(ticketransferEntity.getParentTicketId());
            ticketRetentionIds.add(ticketransferEntity.getTicketRetentionId());
            ticketIds.add(ticketransferEntity.getTicketId());
        }
        Collection<TicketEntity> parent = ticketService.listByIds(parentIds);
        Collection<TicketEntity> ticketRetention = ticketService.listByIds(ticketRetentionIds);
        Collection<TicketEntity> ticket = ticketService.listByIds(ticketIds);
        parent.forEach(e -> {
            e.setCashStatus(TicketCashingEnum.WAITING_FOR_PAYMENT.getCode());
            e.setTicketStatus(TicketStatusEnum.WAITING_PAYMENT.getCode());
        });
        ticketRetention.forEach(e -> {
            e.setTicketStatus(TicketStatusEnum.INVALID.getCode());
            e.setInvalidReason(InvalidReasonEnum.WAITING_PAYMENT.getValue());
        });
        ticket.forEach(e -> {
            e.setTicketStatus(TicketStatusEnum.INVALID.getCode());
            e.setInvalidReason(InvalidReasonEnum.WAITING_PAYMENT.getValue());
        });
        parent.addAll(ticketRetention);
        parent.addAll(ticket);
        ticketService.updateBatchById(parent);
    }

    @Override
    public PageUtils listPlatformApprove(Map<String, Object> params, User user) {
        return this.queryPage(params, user, "2");
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void approveTransferOrder(TicketransferUpdateDto ticketransfer, User user) throws SysException {
        TicketransferEntity ticketransferEntity = this.getById(ticketransfer.getId());
        if (!TicketStatusEnum.TRANSFER_PENDING_APPROVE.getCode().equals(ticketransferEntity.getTicketStatus())) {
            throw new SysException("该票未属于拆转待审批状态，请重新操作！");
        }
        //todo 缺少平台身份检验
        ticketransferEntity.setPlatApprovalTime(new Date());
        ticketransferEntity.setPlatApprovalId(user.getId());
        ticketransferEntity.setPlatApprovalRemarks(ticketransfer.getRecheckRemark());
        //更新子票和留存票及母票数据
        if ("0".equals(ticketransfer.getPassOrReject())) {
            //更新转让申请单数据
            ticketransferEntity.setTicketStatus(TicketStatusEnum.TRANSFER_PENDING_SIGN.getCode());
        } else {
            ticketransferEntity.setTicketStatus(TicketStatusEnum.APPROVE_REJECT.getCode());
        }
        //处理转让涉及的票状态
        this.changeStatus(ticketransferEntity, ticketransfer.getPassOrReject(), TicketStatusEnum.TRANSFER_PENDING_SIGN.getCode(), false);
        this.updateById(ticketransferEntity);
    }

    /**
     * 获取 转让 达到预兑付的 票据
     *
     * @param days 提前预兑付的日期
     * @return 达到预兑付的 票据
     */
    private List<TicketransferEntity> getAdvanceTransferTicket(Integer days) {
        // 截至兑付日期
        Date cashTime = DateUtils.dateAddDaysAll(days);
        if (ObjectUtils.isEmpty(cashTime)) {
            return new ArrayList<>();
        }
        QueryWrapper<TicketransferEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TicketransferEntity::getAdvancePaymentStatus, 0)
                // 当转让 签收的状态为 签收或者拒绝 则 不能进行 预兑付 反之则可以进行预兑付
                .in(TicketransferEntity::getTicketStatus, Arrays.asList(4, 5, 6, 7, 8))
                .le(TicketransferEntity::getExpireTime, cashTime);
        List<TicketransferEntity> list = this.list(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        return list;
    }

    @Override
    public PageUtils queryPageApprove(Map<String, Object> params, User user) {
        return this.queryPage(params, user, "1");
    }

    /**
     * 根据票据状态和 兑付时间 计算剩余时间
     *
     * @param cashTime     兑付时间
     * @param ticketStatus 票据状态
     * @return 剩余兑付时间
     */
    @Override
    public String calculateSurplusDays(Date cashTime, Integer ticketStatus) {
        // 如果票据转台为 为 已兑付
        if (ObjectUtils.isEmpty(cashTime)) {
            return "";
        }
        Date now = new Date();
        if (ticketStatus.equals(TicketStatusEnum.PAID.getCode())) {
            return "-";
        } else {
            // 未兑付
            long days;
            if (now.before(cashTime)) {
                // 计算剩余兑付 时间
                days = (cashTime.getTime() - now.getTime()) / (1000L * 3600L * 24L);
                return "剩余" + days + " 天";
            } else {
                // 逾期
                days = (now.getTime() - cashTime.getTime()) / (1000L * 3600L * 24L);
                return "已逾期" + days + "天";
            }
        }
    }

    /**
     * 新增
     *
     * @param ticketTransferAddDto 新增实体
     * @param user                 当前登录用户
     * @throws SysException 业务异常
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String saveTicketransfer(TicketransferAddDto ticketTransferAddDto, User user) throws SysException {
        TicketransferEntity ticketTransferEntity = new TicketransferEntity();
        TicketEntity parentTicket = ticketService.getById(ticketTransferAddDto.getParentTicketId());
        TicketOpenEntity ticketOpenEntity = ticketOpenService.getById(parentTicket.getTicketOpenId());
        //校验
        this.parameterVerification(user, parentTicket, ticketTransferAddDto);
        BeanUtils.copyProperties(ticketTransferAddDto, ticketTransferEntity);
        this.saveEntity(ticketTransferEntity, parentTicket, ticketTransferAddDto, user, ticketOpenEntity);
        // 4.保存转让相关的附件资料
        ticketTransferAddDto.getProofList().addAll(ticketTransferAddDto.getInvoiceList());
        List<TicketDataTransferAddDto> fileList = ticketTransferAddDto.getProofList();
        if (!CollectionUtils.isEmpty(ticketTransferAddDto.getProofList())) {
            fileList.forEach(x -> {
                x.setTicketActionType(TicketActionTypeEnum.TICKET_TYPE_TRANSFER.getCode());
                x.setTicketActionId(ticketTransferEntity.getId());
                x.setTicketNo(ticketTransferEntity.getTicketNo());
                x.setApplyId(ticketTransferEntity.getId());
            });
            ticketDataService.saveTicketTransferData(fileList, user);
        }
        //保存转让申请单操作记录
        this.saveTicketLog(ticketTransferEntity, ticketTransferAddDto, user);

        //  拉起转单复核协议
//        ticketFinanceService.setBusinessProtocol(ticketTransferEntity.getId(), ContractTicketTypeEnum.TICKET_TYPE_TRANSFER.getCode());
        //拉起审核流程，并发送消息
        String msg = MailMessageConstant.TICKET_TRANSFER_APPROVE.replace(MailMessageConstant.TICKET_REPLACE_APPLY, user.getUsername())
                .replace(MailMessageConstant.TICKET_REPLACE_SIGN, ticketTransferAddDto.getReceiveEnterpriseName())
                .replace(MailMessageConstant.TICKET_REPLACE_MONEY, NumberUtil.numberFormatString(ticketTransferAddDto.getTransferAmount()));
        MsgInfoDto msgInfoDto = new MsgInfoDto(ticketTransferEntity.getId(), GotoTypeEnum.GOTO_TYPE_TRANSFER.getCode().toString(), msg, null);
        //开始转让复核流程
        ticketProcessService.saveTicketProcess(ticketTransferAddDto.getTransferAmount()
                , ticketTransferEntity.getId(), JSON.toJSONString(msgInfoDto), ApproveTypeEnum.TRANSFER, user, null
                , TicketActionTypeEnum.TICKET_TYPE_TRANSFER.getCode().toString());
        //处理开启审批
        ticketTransferEntity.setTicketStatus(TicketStatusEnum.TRANSFER_PENDING_REVIEW.getCode());
        if (!this.updateById(ticketTransferEntity)) {
            throw new SysException("A00001", "编辑失败！");
        }
        //保存票据操作记录
        this.saveTransferFlowChart(ticketTransferEntity, user);
        return ticketTransferEntity.getId();
    }

    private void saveTransferFlowChart(TicketransferEntity ticketTransferEntity, User user) throws SysException {
        TicketFlowChartEntity parentEntity = ticketFlowChartService.getOneByTicketId(ticketTransferEntity.getParentTicketId());
        //修改父票颜色为蓝色
        parentEntity.setTicketStatus("0");
        ticketFlowChartService.updateById(parentEntity);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DateUtils.DF_YYYY_MM_DD);
        TicketFlowChartEntity ticketFlowChartEntity = new TicketFlowChartEntity();
        ticketFlowChartEntity.setTitle("凭证编号：" + ticketTransferEntity.getTicketNo());
        ticketFlowChartEntity.setInitiatorEnterpriseName(ticketTransferEntity.getTransferEnterpriseName());
        ticketFlowChartEntity.setSignEnterpriseName("转让签收企业：" + ticketTransferEntity.getReceiveEnterpriseName());
        ticketFlowChartEntity.setMoneyAmountFirst("凭证金额：" + StrUtils.simgleFormat(ticketTransferEntity.getTransferAmount()) + " 元");
        ticketFlowChartEntity.setEnterpriseId(ticketTransferEntity.getReceiveEnterpriseId());
        ticketFlowChartEntity.setFirstTime("转让日期：" + simpleDateFormat.format(ticketTransferEntity.getCreateTime()));
        ticketFlowChartEntity.setUppercaseAmount("人民币" + NumberToCN.number2CNMontrayUnit(BigDecimal.valueOf(ticketTransferEntity.getTransferAmount())));
        ticketFlowChartEntity.setApplyId(ticketTransferEntity.getId());
        ticketFlowChartEntity.setParentId(parentEntity.getId());
        ticketFlowChartEntity.setTicketId(ticketTransferEntity.getTicketId());
        ticketFlowChartEntity.setType("0");
        ticketFlowChartEntity.setTicketOpenId(ticketTransferEntity.getTicketOpenId());
        ticketFlowChartEntity.setTicketStatus("2");
        if (StringUtils.isNotBlank(ticketTransferEntity.getTicketRetentionId())) {
            TicketFlowChartEntity retentionFlowChartEntity = new TicketFlowChartEntity();
            retentionFlowChartEntity.setTitle("凭证编号：" + ticketTransferEntity.getTicketRetentionNo());
            retentionFlowChartEntity.setSignEnterpriseName(parentEntity.getSignEnterpriseName());
            retentionFlowChartEntity.setMoneyAmountFirst("凭证金额：" + StrUtils.simgleFormat(ticketTransferEntity.getTicketRetentionAmount()) + " 元");
            retentionFlowChartEntity.setEnterpriseId(ticketTransferEntity.getTransferEnterpriseId());
            retentionFlowChartEntity.setFirstTime("转让日期：" + simpleDateFormat.format(ticketTransferEntity.getCreateTime()));
            retentionFlowChartEntity.setUppercaseAmount("人民币" + NumberToCN.number2CNMontrayUnit(BigDecimal.valueOf(ticketTransferEntity.getSurplusAmount())));
            retentionFlowChartEntity.setApplyId(ticketTransferEntity.getId());
            retentionFlowChartEntity.setParentId(parentEntity.getId());
            retentionFlowChartEntity.setTicketId(ticketTransferEntity.getTicketRetentionId());
            retentionFlowChartEntity.setType("0");
            retentionFlowChartEntity.setTicketOpenId(ticketTransferEntity.getTicketOpenId());
            retentionFlowChartEntity.setTicketStatus("2");
            ticketFlowChartService.saveTicketFlowChartEntity(Arrays.asList(ticketFlowChartEntity, retentionFlowChartEntity), user);
        } else {
            ticketFlowChartService.saveTicketFlowChartEntity(Collections.singletonList(ticketFlowChartEntity), user);
        }

    }

    private void saveTicketLog(TicketransferEntity ticketTransferEntity, TicketransferAddDto ticketTransferAddDto, User user) {
        List<TicketOperateLogEntity> adds = new ArrayList<>();
        TicketOperateLogEntity ticketOperateLogEntity = ticketOperateLogService.getTicketOperateLogEntity(LogActionTypeEnum.TICKET_TYPE_TRANSFER.getCode(), ticketTransferEntity.getId()
                , TicketLogStatusEnum.START.getCode(), OperateLogTypeEnum.TRANSFER.getCode(), TicketLogStatusEnum.TRANSFER_PENDING_REVIEW.getCode(), user
                , ticketTransferAddDto.getReceiveRemark(),
                ticketTransferEntity.getReceiveEnterpriseId(), ticketTransferEntity.getReceiveEnterpriseName(),
                ticketTransferEntity.getTransferEnterpriseId(), ticketTransferEntity.getTransferEnterpriseName(), ticketTransferEntity.getTicketId(), "0", null, null);
        TicketOperateLogEntity parentLog = ticketOperateLogService.getTicketOperateLogEntity(LogActionTypeEnum.TICKET_TYPE_TRANSFER.getCode(), ticketTransferEntity.getId()
                , TicketLogStatusEnum.TRANSFER_SUCCESS.getCode(), OperateLogTypeEnum.TRANSFER.getCode(), TicketLogStatusEnum.INVALID.getCode(), user
                , ticketTransferAddDto.getReceiveRemark(),
                ticketTransferEntity.getReceiveEnterpriseId(), ticketTransferEntity.getReceiveEnterpriseName(),
                ticketTransferEntity.getTransferEnterpriseId(), ticketTransferEntity.getTransferEnterpriseName(), ticketTransferEntity.getParentTicketId(), "1", null, null);
        if (StringUtils.isNotBlank(ticketTransferEntity.getTicketRetentionId())) {
            TicketOperateLogEntity childLog = ticketOperateLogService.getTicketOperateLogEntity(LogActionTypeEnum.TICKET_TYPE_TRANSFER.getCode(), ticketTransferEntity.getId()
                    , TicketLogStatusEnum.TRANSFER_SUCCESS.getCode(), OperateLogTypeEnum.TRANSFER.getCode(), TicketLogStatusEnum.TRANSFER_RETAINED.getCode(), user
                    , ticketTransferAddDto.getReceiveRemark(),
                    ticketTransferEntity.getReceiveEnterpriseId(), ticketTransferEntity.getReceiveEnterpriseName(),
                    ticketTransferEntity.getTransferEnterpriseId(), ticketTransferEntity.getTransferEnterpriseName(), ticketTransferEntity.getTicketRetentionId(), "1", null, null);
            adds.add(childLog);
        }
        adds.add(ticketOperateLogEntity);
        adds.add(parentLog);
        ticketOperateLogService.saveBatch(adds);
    }

    private void saveEntity(TicketransferEntity ticketransferEntity, TicketEntity parentTicket, TicketransferAddDto ticketransferAddDto, User user, TicketOpenEntity ticketOpenEntity) throws SysException {
        //获取转让方统一信用代码
        Map<String,String> map=baseDataFeign.getSocialCreditCode(new StringIds(Collections.singletonList(parentTicket.getEnterpriseId())));
        ticketransferEntity.setTransferCreditCode(map.get(parentTicket.getEnterpriseId()));
        ticketransferEntity.setTicketOpenId(parentTicket.getTicketOpenId());
        ticketransferEntity.setTransferNo(TicketNoUtils.getTicketTransferNo(redisTemplate));
        ticketransferEntity.setParentTicketNo(parentTicket.getTicketNo());
        ticketransferEntity.setParentAmount(parentTicket.getTicketSurplusAmount());
        ticketransferEntity.setExpireTime(parentTicket.getCashTime());
        ticketransferEntity.setTransferEnterpriseId(parentTicket.getEnterpriseId());
        ticketransferEntity.setTransferEnterpriseName(parentTicket.getEnterpriseName());
        String transferId = UuidUtils.UUID();
        //子单
        TicketEntity subOrderTicket = this.generateSubOrderTicketEntity(ticketransferAddDto, user, parentTicket, transferId);
        TicketEntity retentionTicket = null;
        if (!ticketransferAddDto.getTransferAmount().equals(parentTicket.getTicketSurplusAmount())) {
            //要存储的留存单信息
            retentionTicket = this.generateRetentionTicketEntity(ticketransferAddDto, user, parentTicket, transferId);
        }
        if (retentionTicket != null) {
            ticketService.saveBatch(asList(subOrderTicket, retentionTicket));
        } else {
            ticketService.save(subOrderTicket);
        }
        //父单信息处理，1 修改父单状态
        this.parentTicketProcess(ticketransferAddDto, parentTicket);
        ticketransferEntity.setId(transferId);
        ticketransferEntity.setTicketId(subOrderTicket.getId());
        ticketransferEntity.setTicketNo(subOrderTicket.getTicketNo());
        if (retentionTicket != null) {
            ticketransferEntity.setTicketRetentionId(retentionTicket.getId());
            ticketransferEntity.setTicketRetentionNo(retentionTicket.getTicketNo());
            ticketransferEntity.setTicketRetentionAmount(retentionTicket.getTicketSurplusAmount());
            ticketransferEntity.setSurplusAmount(retentionTicket.getTicketAllAmount());
        }
        ticketransferEntity.setInvoiceTime(parentTicket.getInvoiceTime());
        ticketransferEntity.setExpireTime(parentTicket.getExpireTime());
        ticketransferEntity.setTicketStatus(TicketStatusEnum.TRANSFER_PENDING_REVIEW.getCode());
        ticketransferEntity.setParentTicketId(parentTicket.getId());
        ticketransferEntity.setParentTicketNo(parentTicket.getTicketNo());
        ticketransferEntity.setParentAmount(parentTicket.getTicketSurplusAmount());
        ticketransferEntity.setAdvancePaymentStatus(0);
        ticketransferEntity.setEnterpriseId(ticketransferEntity.getTransferEnterpriseId());
        ticketransferEntity.setOrgId(user.getOrgId());
        ticketransferEntity.setCreatorId(user.getId());
        ticketransferEntity.setInstinctyId(parentTicket.getInstinctyId());
        ticketransferEntity.setInstinctyName(parentTicket.getInstinctyName());
        ticketransferEntity.setOpenEnterpriseId(parentTicket.getOpenEnterpriseId());
        ticketransferEntity.setOpenEnterpriseName(parentTicket.getOpenEnterpriseName());
        ticketransferEntity.setOpenCreditCode(ticketOpenEntity.getOpenSocialCreditCode());
        if (!this.save(ticketransferEntity)) {
            throw new SysException("A00001", "保存失败！");
        }

    }

    private void parameterVerification(User user, TicketEntity parentTicket, TicketransferAddDto ticketransferAddDto) throws SysException {
        if (parentTicket.getCirculationEnterpriseFlag().equals(CirculationEnterpriseFlagStatusEnum.YES.getCode())) {
            TicketCirculationEnterpriseEntity circulationEnterpriseEntity =
                    ticketCirculationEnterpriseService.getByTicketOpenIdAndCirculationEnterpriseId(parentTicket.getTicketOpenId(), ticketransferAddDto.getReceiveEnterpriseId());
            if (circulationEnterpriseEntity == null) {
                throw new SysException("该票不可指定当前选择的收单企业！");
            }
        }
        if (!user.getEnterpriseId().equals(parentTicket.getEnterpriseId()) || user.getUserCategory() != 1) {
            throw new SysException("您未有改权限转让该票！");
        }
        if (!parentTicket.getTicketStatus().equals(TicketStatusEnum.NORMAL_HOLDING.getCode()) || parentTicket.getFrozenState().equals(FrozenStatusEnum.FROZEN_STATUS_YES.getCode())) {
            throw new SysException("转让票不属于正常状态请重新操作！");
        }
        if (ticketransferAddDto.getTransferAmount() > parentTicket.getTicketSurplusAmount()) {
            throw new SysException("转让金额不可大于转让票的金额！");
        }
    }

    private void parentTicketProcess(TicketransferAddDto ticketransferAddDto, TicketEntity parentTicket) throws SysException {
        parentTicket.setTicketStatus(TicketStatusEnum.INVALID.getCode());
        parentTicket.setInvalidReason(InvalidReasonEnum.TICKET_TRANSFER_SUCCESS.getCode());
        ticketManager.remainingAmountAfterDeduction(parentTicket, ticketransferAddDto.getTransferAmount());
    }

    private TicketEntity generateRetentionTicketEntity(TicketransferAddDto ticketransferAddDto, User user, TicketEntity parentTicket, String transferId) {
        TicketEntity retentionTicket = new TicketEntity();
        String retentionId = UuidUtils.UUID();
        retentionTicket.setId(retentionId);
        retentionTicket.setTicketNo(TicketNoUtils.getTicketNo(redisTemplate));
        retentionTicket.setEnterpriseId(parentTicket.getEnterpriseId());
        retentionTicket.setEnterpriseName(parentTicket.getEnterpriseName());
        BigDecimal b1 = new BigDecimal(Double.toString(parentTicket.getTicketSurplusAmount()));
        BigDecimal b2 = new BigDecimal(Double.toString(ticketransferAddDto.getTransferAmount()));
        Double ticketAmount = b1.subtract(b2).doubleValue();
        retentionTicket.setTicketAllAmount(ticketAmount);
        retentionTicket.setTicketAvailableAmount(ticketAmount);
        retentionTicket.setTicketSurplusAmount(ticketAmount);
        retentionTicket.setTransferFrozenAmount(0.0D);
        retentionTicket.setFinanceFrozenAmount(0.0D);
        retentionTicket.setTransferAmount(0.0D);
        retentionTicket.setFinanceAmount(0.0D);
        retentionTicket.setInvoiceTime(new Date());
        retentionTicket.setCashTime(parentTicket.getCashTime());
        retentionTicket.setLimitDays(parentTicket.getLimitDays());
        retentionTicket.setParentBusinessId(transferId);
        retentionTicket.setParentEnterpriseId(parentTicket.getParentEnterpriseId());
        retentionTicket.setParentEnterpriseName(parentTicket.getParentEnterpriseName());
        retentionTicket.setFrozenState(FrozenStatusEnum.FROZEN_STATUS_YES.getCode());
        retentionTicket.setOpenEnterpriseId(parentTicket.getOpenEnterpriseId());
        retentionTicket.setOpenEnterpriseName(parentTicket.getOpenEnterpriseName());
        retentionTicket.setTicketStatus(TicketStatusEnum.NORMAL_HOLDING.getCode());
        retentionTicket.setContractNo(parentTicket.getContractNo());
        retentionTicket.setTicketSource(1);
        if (Arrays.asList(1, 5, 6).contains(parentTicket.getTicketTypeSource())) {
            retentionTicket.setTicketTypeSource(TicketTypeSourceEnum.OPEN_TRANSFER_KEEP.getCode());
        } else {
            retentionTicket.setTicketTypeSource(TicketTypeSourceEnum.TRANSFER_KEEP.getCode());
        }
        retentionTicket.setTicketOpenId(parentTicket.getTicketOpenId());
        retentionTicket.setTicketTransferId(transferId);
        retentionTicket.setParentId(parentTicket.getId());
        retentionTicket.setParentTicketNo(parentTicket.getTicketNo());
        retentionTicket.setAdvancePaymentStatus(0);
        retentionTicket.setOrgId(user.getOrgId());
        retentionTicket.setCreateTime(new Date());
        retentionTicket.setUpdateTime(new Date());
        retentionTicket.setCreatorId(user.getId());
        retentionTicket.setInstinctyId(parentTicket.getInstinctyId());
        retentionTicket.setInstinctyName(parentTicket.getInstinctyName());
        retentionTicket.setReceivableAmount(parentTicket.getReceivableAmount());
        retentionTicket.setTicketOriginId(parentTicket.getId());
        retentionTicket.setCashStatus(parentTicket.getCashStatus());
        retentionTicket.setFrozenState(FrozenStatusEnum.FROZEN_STATUS_YES.getCode());
        retentionTicket.setCirculationEnterpriseFlag(parentTicket.getCirculationEnterpriseFlag());
        retentionTicket.setPaymentMode(parentTicket.getPaymentMode());
        retentionTicket.setTicketOriginNo(parentTicket.getTicketOriginNo());
        retentionTicket.setEnterpriseFreezingStatus(0);
        retentionTicket.setReceiptTime(parentTicket.getReceiptTime());
        retentionTicket.setExpireTime(parentTicket.getExpireTime());
        return retentionTicket;
    }

    /**
     * @param ticketransferAddDto 转让申请单
     * @param user
     * @param fatherTicket        父级票信息
     * @param transferId          转让申请表id
     * @return
     */
    private TicketEntity generateSubOrderTicketEntity(TicketransferAddDto ticketransferAddDto, User user, TicketEntity fatherTicket, String transferId) {
        TicketEntity ticketEntity = new TicketEntity();
        String id = UuidUtils.UUID();
        ticketEntity.setId(id);
        ticketEntity.setTicketNo(TicketNoUtils.getTicketNo(redisTemplate));
        ticketEntity.setEnterpriseId(fatherTicket.getEnterpriseId());
        ticketEntity.setEnterpriseName(fatherTicket.getEnterpriseName());
        ticketEntity.setTicketAllAmount(ticketransferAddDto.getTransferAmount());
        ticketEntity.setTicketAvailableAmount(ticketransferAddDto.getTransferAmount());
        ticketEntity.setTicketSurplusAmount(ticketransferAddDto.getTransferAmount());
        ticketEntity.setTransferFrozenAmount(0.0D);
        ticketEntity.setFinanceFrozenAmount(0.0D);
        ticketEntity.setTransferAmount(0.0D);
        ticketEntity.setFinanceAmount(0.0D);
        ticketEntity.setParentBusinessId(transferId);
        ticketEntity.setInvoiceTime(new Date());
        ticketEntity.setCashTime(fatherTicket.getCashTime());
        ticketEntity.setLimitDays(fatherTicket.getLimitDays());
        ticketEntity.setParentEnterpriseId(user.getEnterpriseId());
        ticketEntity.setParentEnterpriseName(fatherTicket.getEnterpriseName());
        ticketEntity.setTransferEnterpriseId(fatherTicket.getEnterpriseId());
        ticketEntity.setTransferEnterpriseName(fatherTicket.getEnterpriseName());
        ticketEntity.setTicketStatus(TicketStatusEnum.TRANSFER_PENDING_REVIEW.getCode());
        ticketEntity.setOpenEnterpriseId(fatherTicket.getOpenEnterpriseId());
        ticketEntity.setOpenEnterpriseName(fatherTicket.getOpenEnterpriseName());
        ticketEntity.setTicketSource(1);
        ticketEntity.setTicketTypeSource(TicketTypeSourceEnum.TRANSFER.getCode());
        ticketEntity.setTicketOpenId(fatherTicket.getTicketOpenId());
        ticketEntity.setTicketTransferId(transferId);
        ticketEntity.setParentId(fatherTicket.getId());
        ticketEntity.setParentTicketNo(fatherTicket.getTicketNo());
        ticketEntity.setAdvancePaymentStatus(0);
        ticketEntity.setOrgId(user.getOrgId());
        ticketEntity.setCreateTime(new Date());
        ticketEntity.setUpdateTime(new Date());
        ticketEntity.setCreatorId(user.getId());
        ticketEntity.setInstinctyId(fatherTicket.getInstinctyId());
        ticketEntity.setInstinctyName(fatherTicket.getInstinctyName());
        ticketEntity.setTicketOriginId(fatherTicket.getId());
        ticketEntity.setCashStatus(fatherTicket.getCashStatus());
        ticketEntity.setFrozenState(0);
        ticketEntity.setCirculationEnterpriseFlag(fatherTicket.getCirculationEnterpriseFlag());
        ticketEntity.setPaymentMode(fatherTicket.getPaymentMode());
        ticketEntity.setTicketOriginNo(fatherTicket.getTicketOriginNo());
        ticketEntity.setEnterpriseFreezingStatus(0);
        ticketEntity.setTransferTime(new Date());
        ticketEntity.setExpireTime(fatherTicket.getExpireTime());
        return ticketEntity;
    }

    @Override
    public TicketTransferInfo info(String id) {
        TicketransferEntity ticketransferEntity = this.getById(id);
        //父票id
        TicketEntity parentTicket = ticketService.getById(ticketransferEntity.getParentTicketId());
        TicketTransferInfo ticketTransferInfo = new TicketTransferInfo();
        BeanUtils.copyProperties(ticketransferEntity, ticketTransferInfo);

        ticketTransferInfo.setHandStatusInfo(TicketStatusEnum.getStatusHandInfo(ticketTransferInfo.getTicketStatus()));
        if (TicketStatusEnum.REJECT_LIST.contains(ticketTransferInfo.getTicketStatus()) ||
                TicketStatusEnum.CANCEL.getCode().equals(ticketTransferInfo.getTicketStatus())) {
            ticketTransferInfo.setHandStatus("失败");
        } else if (TicketStatusEnum.TRANSFER_IN_LIST.contains(ticketTransferInfo.getTicketStatus())) {
            ticketTransferInfo.setHandStatus("转让中");
        } else if (TicketStatusEnum.SUCCESS_IN_LIST.contains(ticketTransferInfo.getTicketStatus())) {
            ticketTransferInfo.setHandStatus("成功");
        }
        String surplusDays = this.calculateSurplusDays(parentTicket.getCashTime(), parentTicket.getTicketStatus());
        ticketTransferInfo.setSurplusCashingDays(surplusDays);
        ticketTransferInfo.setPaymentModeInfo(PaymentModeEnum.getValue(parentTicket.getPaymentMode()));
        // 找到转让相关附件信息
        List<TicketDataEntity> dataEntities = ticketDataService.getByTicketId(id, TicketActionTypeEnum.TICKET_TYPE_TRANSFER.getCode());
        if (!CollectionUtils.isEmpty(dataEntities)) {
            Map<String, List<TicketDataEntity>> map = dataEntities.stream().collect(Collectors.groupingBy(TicketDataEntity::getDataType));
            ticketTransferInfo.setInvoiceList(map.get(DataTypeEnum.INVOICE.getCode()));
            ticketTransferInfo.setProofList(map.get(DataTypeEnum.TICKET.getCode()));
        }
        ticketTransferInfo.setHandProgress(TicketStatusEnum.getProgress(ticketTransferInfo.getTicketStatus()));
        return this.setTransferContract(ticketTransferInfo);
    }

    /**
     * 设置签署资料
     *
     * @param ticketTransferInfo 转单详情
     * @return
     */
    private TicketTransferInfo setTransferContract(TicketTransferInfo ticketTransferInfo) {
        TicketContractListDto ticketContractListDto = new TicketContractListDto();
        ticketContractListDto.setTicketId(ticketTransferInfo.getId());
        ticketContractListDto.setTicketType(ContractTicketTypeEnum.TICKET_TYPE_TRANSFER.getCode());
        List<BusinessContractEntity> contractEntities = businessContractService.getByTicketId(ticketTransferInfo.getId(), BusinessTypeEnum.TICKET_TRANSFER.getCode());
        ticketTransferInfo.setProtocolList(contractEntities);
        return ticketTransferInfo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void recheckTransferOrder(ApprovalSubmitDto approvalSubmitDto, User user) throws SysException {

        // 如果 转让的票被锁定则 不用发 rpc
        TicketransferEntity entity = this.getById(approvalSubmitDto.getId());
        if (ObjectUtils.isEmpty(entity)) {
            throw new SysException("未找到当前转让申请!");
        }
        if (!TicketStatusEnum.TRANSFER_PENDING_REVIEW.getCode().equals(entity.getTicketStatus())) {
            throw new SysException("改票未处于复核状态！");
        }
        Result userInfo = userFeign.getUserInfo(entity.getCreatorId());
        if (ResultCode.SUCCESS.getCode() != userInfo.getCode()) {
            throw new SysException("当前申请人不存在！");
        }
        //拼接发送消息
        QueryWrapper<TicketProcessEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("ticket_transfer_id", approvalSubmitDto.getId());
        queryWrapper.eq("approve_type", ApproveTypeEnum.TRANSFER.getCode());
        TicketProcessEntity processEntity = ticketProcessService.getOne(queryWrapper);
        if (null == processEntity) {
            throw new SysException("审批流程不存在!");
        }
        approvalSubmitDto.setApprovalId(processEntity.getApproveId());
        approvalSubmitDto.setTicketId(entity.getTicketId());
        //保存要发送的消息
        this.saveMessageContent(approvalSubmitDto, userInfo, entity);
        //调用流程服务的去审核
        Result result = processFeign.processSubmit(approvalSubmitDto);
        if (ResultCode.SUCCESS.getCode() != result.getCode()) {
            throw new SysException(result.getMsg());
        }
    }

    /**
     * 处理转让涉及的票状态
     *
     * @param entity
     * @param passOrReject 通过或驳回
     * @param childStatus  子票状态
     * @param bo           是否是签收状态
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeStatus(TicketransferEntity entity, String passOrReject, Integer childStatus, boolean bo) throws SysException {
        //更新子票和留存票及母票数据
        List<String> ticketIds = new ArrayList<>();
        ticketIds.add(entity.getParentTicketId());
        ticketIds.add(entity.getTicketId());
        if (StringUtils.isNotBlank(entity.getTicketRetentionId())) {
            ticketIds.add(entity.getTicketRetentionId());
        }
        List<TicketEntity> ticketEntities = new ArrayList<>(ticketService.listByIds(ticketIds));
        List<TicketEntity> needUpdateEntities = new ArrayList<>();
        TicketEntity parentEntity = ticketEntities.stream().filter(t -> t.getId().equals(entity.getParentTicketId())).findFirst().get();
        TicketEntity childEntity = ticketEntities.stream().filter(t -> t.getId().equals(entity.getTicketId())).findFirst().get();
        TicketEntity retentionEntity = null;
        Optional<TicketEntity> retentionEntityOp = ticketEntities.stream().filter(t -> t.getId().equals(entity.getTicketRetentionId())).findFirst();
        if (retentionEntityOp.isPresent()) {
            retentionEntity = retentionEntityOp.get();
        }
        if (ApproveResultStatusEnum.APPROVE_STATUS_YES.getCode().equals(passOrReject)) {
            childEntity.setTicketStatus(childStatus);
            childEntity.setReceiptTime(new Date());
            if (bo) {
                ticketManager.transferSuccessfulProcessingTicket(parentEntity, entity.getTransferAmount());
                childEntity.setEnterpriseId(entity.getReceiveEnterpriseId());
                childEntity.setEnterpriseName(entity.getReceiveEnterpriseName());
                if (retentionEntity != null) {
                    retentionEntity.setFrozenState(FrozenStatusEnum.FROZEN_STATUS_NO.getCode());
                }
            } else {
                retentionEntity = null;
            }
        } else {
            //失败
            parentEntity.setTicketStatus(TicketStatusEnum.NORMAL_HOLDING.getCode());
            parentEntity.setInvalidReason("");
            ticketManager.transferFailProcessingTicket(parentEntity, entity.getTransferAmount());
            childEntity.setTicketStatus(TicketStatusEnum.INVALID.getCode());
            childEntity.setInvalidReason(InvalidReasonEnum.TICKET_TRANSFER_FAIL.getValue());
            if (retentionEntity != null) {
                retentionEntity.setTicketStatus(TicketStatusEnum.INVALID.getCode());
                retentionEntity.setInvalidReason(InvalidReasonEnum.TICKET_TRANSFER_CHILD_FAIL.getValue());
            }
        }
        needUpdateEntities.add(parentEntity);
        needUpdateEntities.add(childEntity);
        if (retentionEntity != null) {
            needUpdateEntities.add(retentionEntity);
        }
        ticketService.updateBatchById(needUpdateEntities);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void signTransferOrder(ApprovalSubmitDto approvalSubmitDto, User user) throws SysException {
        TicketransferEntity ticketransferEntity = this.getById(approvalSubmitDto.getId());
        if (!TicketStatusEnum.TRANSFER_PENDING_SIGN.getCode().equals(ticketransferEntity.getTicketStatus())) {
            throw new SysException("该票未属于待签收状态，请重新操作！");
        }
        if (!user.getEnterpriseId().equals(ticketransferEntity.getReceiveEnterpriseId())) {
            throw new SysException("该票未属于您公司，请重新操作！");
        }

        // 如果 转让的票被锁定则 不用发 rpc
        TicketransferEntity entity = this.getById(approvalSubmitDto.getId());
        if (ObjectUtils.isEmpty(entity)) {
            throw new SysException("未找到当前转让申请");
        }

        Result userInfo = userFeign.getUserInfo(entity.getCreatorId());
        if (ResultCode.SUCCESS.getCode() != userInfo.getCode()) {
            throw new SysException("当前申请人不存在");
        }
        //拼接发送消息
        QueryWrapper<TicketProcessEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TicketProcessEntity::getTicketTransferId, ticketransferEntity.getId())
        .eq(TicketProcessEntity::getApproveType,ApproveTypeEnum.SIGN_TRANSFER.getCode());
        TicketProcessEntity processEntity = ticketProcessService.getOne(queryWrapper);
        if (null == processEntity) {
            throw new SysException("审批流程不存在");
        }
        approvalSubmitDto.setApprovalId(processEntity.getApproveId());

        String msg = MailMessageConstant.TICKET_TRANSFER_SIGN_APPROVE.replace(MailMessageConstant.TICKET_REPLACE_TRANSFER, entity.getTransferEnterpriseName())
                .replace(MailMessageConstant.TICKET_REPLACE_MONEY
                        , NumberUtil.numberFormatString(entity.getTransferAmount()));
        MsgInfoDto msgInfoDto = new MsgInfoDto(approvalSubmitDto.getId(), GotoTypeEnum.GOTO_TYPE_SIGN_TRANSFER.getCode().toString(), msg, null);

        String ccMsg = MailMessageConstant.TICKET_TRANSFER_SIGN_APPROVE_CC.replace(MailMessageConstant.TICKET_REPLACE_TRANSFER, entity.getTransferEnterpriseName())
                .replace(MailMessageConstant.TICKET_REPLACE_MONEY
                        , NumberUtil.numberFormatString(entity.getTransferAmount()));
        MsgInfoDto ccMsgInfoDto = new MsgInfoDto(approvalSubmitDto.getId(), GotoTypeEnum.GOTO_TYPE_SIGN_TRANSFER.getCode().toString(), ccMsg, null);

        approvalSubmitDto.setMsg(JSON.toJSONString(msgInfoDto));
        approvalSubmitDto.setCcMsg(JSON.toJSONString(ccMsgInfoDto));
        approvalSubmitDto.setApprovalType(ApproveTypeEnum.SIGN_OPEN_TRANSFER.getCode());
        approvalSubmitDto.setApplyType("1");
        approvalSubmitDto.setTicketId(ticketransferEntity.getTicketId());
        //调用流程服务的去审核
        Result result = processFeign.processSubmit(approvalSubmitDto);
        if (ResultCode.SUCCESS.getCode() != result.getCode()) {
            throw new SysException(result.getMsg());
        }

    }

    @Override
    public StatisticsDataDto getTransferData(User user) {
        return baseMapper.getTransferData(user.getEnterpriseId());
    }

    public double sub(double v1, double v2) {

        BigDecimal b1 = new BigDecimal(Double.toString(v1));

        BigDecimal b2 = new BigDecimal(Double.toString(v2));

        return b1.subtract(b2).doubleValue();

    }

    /**
     *   * double类型加法
     * <p>
     *   * @param v1
     * <p>
     *   * @param v2
     * <p>
     *   * @return
     * <p>
     *  
     */
    public double add(double v1, double v2) {

        BigDecimal b1 = new BigDecimal(Double.toString(v1));

        BigDecimal b2 = new BigDecimal(Double.toString(v2));

        return b1.add(b2).doubleValue();

    }


    private void saveMessageContent(ApprovalSubmitDto approvalSubmitDto, Result userInfo, TicketransferEntity entity) {
        if (approvalSubmitDto.getApprovalResult().equals(ApproveResultStatusEnum.APPROVE_STATUS_YES.getCode())) {
            UserDto userDto = JSON.parseObject(JSON.toJSONString(userInfo.getResult().get("data")), UserDto.class);

            String msg = MailMessageConstant.TICKET_TRANSFER_APPROVE.replace(MailMessageConstant.TICKET_REPLACE_APPLY, userDto.getUserName())
                    .replace(MailMessageConstant.TICKET_REPLACE_SIGN, entity.getReceiveEnterpriseName()).replace(MailMessageConstant.TICKET_REPLACE_MONEY
                            , NumberUtil.numberFormatString(entity.getTransferAmount()));

            MsgInfoDto msgInfoDto = new MsgInfoDto(approvalSubmitDto.getId(), GotoTypeEnum.GOTO_TYPE_TRANSFER.getCode().toString(), msg, null);

            String ccMsg = MailMessageConstant.TICKET_TRANSFER_APPROVE_CC.replace(MailMessageConstant.TICKET_REPLACE_APPLY, userDto.getUserName())
                    .replace(MailMessageConstant.TICKET_REPLACE_SIGN, entity.getReceiveEnterpriseName()).replace(MailMessageConstant.TICKET_REPLACE_MONEY
                            , NumberUtil.numberFormatString(entity.getTransferAmount()));
            MsgInfoDto ccMsgInfoDto = new MsgInfoDto(approvalSubmitDto.getId(), GotoTypeEnum.GOTO_TYPE_TRANSFER.getCode().toString(), ccMsg, null);
            approvalSubmitDto.setMsg(JSON.toJSONString(msgInfoDto));
            approvalSubmitDto.setCcMsg(JSON.toJSONString(ccMsgInfoDto));
        } else {
            String msg = MailMessageConstant.TICKET_TRANSFER_FAIL_APPROVE.replace(MailMessageConstant.TICKET_REPLACE_SIGN, entity.getReceiveEnterpriseName())
                    .replace(MailMessageConstant.TICKET_REPLACE_MONEY, NumberUtil.numberFormatString(entity.getTransferAmount()));
            MsgInfoDto msgInfoDto = new MsgInfoDto(approvalSubmitDto.getId(), GotoTypeEnum.GOTO_TYPE_TRANSFER.getCode().toString(), msg, null);
            approvalSubmitDto.setMsg(JSON.toJSONString(msgInfoDto));
        }
    }


    @Override
    public void transferReviewCallback(NoticeApprovalResult noticeApprovalResult, TicketProcessEntity ticketProcessEntity, User user) throws SysException {
        TicketransferEntity ticketTransferEntity = baseMapper.selectById(ticketProcessEntity.getTicketTransferId());
        if (ObjectUtils.isEmpty(ticketTransferEntity)) {
            throw new SysException("未找到当前转让申请");
        }
        //申请人的消息内容
        String msg = null;
        String signMsg = null;
        //转让审批被驳回
        if (ApproveResultStatusEnum.APPROVE_STATUS_NO.getCode().equals(noticeApprovalResult.getApprovalResult())) {
            //设置审批状态为驳回
            ticketTransferEntity.setTicketStatus(TicketStatusEnum.REVIEW_REJECT.getCode());
            ticketProcessEntity.setApproveStatus(ApproveProcessEnum.APPROVE_PROCESS_FAIL.getCode());
            //给申请人发送复核未通过消息
            msg = MailMessageConstant.TICKET_TRANSFER_FAIL_APPROVE_APPLY.replace(MailMessageConstant.TICKET_REPLACE_SIGN, ticketTransferEntity.getReceiveEnterpriseName())
                    .replace(MailMessageConstant.TICKET_REPLACE_MONEY, NumberUtil.numberFormatString(ticketTransferEntity.getTransferAmount()));
            //更新子票和留存票及母票数据
            this.cancelTicket(ticketTransferEntity);

            //保存转让复核失败票据操作记录
            this.saveReviewFailLog(ticketTransferEntity, noticeApprovalResult, user);
            //处理票据流程图
            this.cancelTransferFlowChart(ticketTransferEntity, user);
        } else {//处理审批通过
            //设置签收状态为待签收
            //todo 暂时设置为待签收
//            ticketTransferEntity.setTicketStatus(TicketStatusEnum.TRANSFER_PENDING_APPROVE.getCode());
            ticketTransferEntity.setTicketStatus(TicketStatusEnum.TRANSFER_PENDING_SIGN.getCode());
            ticketProcessEntity.setApproveStatus(ApproveProcessEnum.APPROVE_PROCESS_SUCESS.getCode());
            //给申请人发送复核通过消息
            msg = MailMessageConstant.TICKET_TRANSFER_APPROVE_APPLY.replace(MailMessageConstant.TICKET_REPLACE_SIGN, ticketTransferEntity.getReceiveEnterpriseName())
                    .replace(MailMessageConstant.TICKET_REPLACE_MONEY, NumberUtil.numberFormatString(ticketTransferEntity.getTransferAmount()));
            //给平台审核人员发送消息
            signMsg = MailMessageConstant.TICKET_TRANSFER_APPROVE_PLAT.replace(MailMessageConstant.TICKET_REPLACE_TRANSFER, ticketTransferEntity.getTransferEnterpriseName())
                    .replace(MailMessageConstant.TICKET_REPLACE_SIGN, ticketTransferEntity.getReceiveEnterpriseId())
                    .replace(MailMessageConstant.TICKET_REPLACE_MONEY, NumberUtil.numberFormatString(ticketTransferEntity.getTransferAmount()));
            //todo 获取平台审批用户ids
            List<String> platIds = new ArrayList<>();
            //给平台审核人员发送消息
            sendMsgService.sendMsgToAllNotifierWithBtnName(ticketTransferEntity.getId(), platIds
                    , GotoTypeEnum.GOTO_TYPE_TRANSFER.getCode().toString(), signMsg, user, null, "详情,去审核");

            ticketOperateLogService.saveTicketLog(LogActionTypeEnum.TICKET_TYPE_TRANSFER.getCode(), ticketTransferEntity.getId()
                    , TicketLogStatusEnum.TRANSFER_PENDING_REVIEW.getCode(), OperateLogTypeEnum.REVIEW_REJECTION.getCode(), TicketLogStatusEnum.TRANSFER_PENDING_APPROVE.getCode(), user
                    , noticeApprovalResult.getApprovalRemark(),
                    ticketTransferEntity.getReceiveEnterpriseId(), ticketTransferEntity.getReceiveEnterpriseName(),
                    ticketTransferEntity.getTransferEnterpriseId(), ticketTransferEntity.getTransferEnterpriseName(), ticketTransferEntity.getTicketId(), "0", null, null
                    , noticeApprovalResult);

            //todo 开启签收流程
            //拉起审核流程，并发送消息
            MsgInfoDto msgInfoDto = new MsgInfoDto(ticketTransferEntity.getId(), GotoTypeEnum.GOTO_TYPE_SIGN_TRANSFER.getCode().toString(), msg, null);
            //开始转让复核流程
            ticketProcessService.saveTicketProcess(ticketTransferEntity.getTransferAmount()
                    , ticketTransferEntity.getId(), JSON.toJSONString(msgInfoDto), ApproveTypeEnum.SIGN_TRANSFER, user, ticketTransferEntity.getReceiveEnterpriseId()
                    , TicketActionTypeEnum.TICKET_TYPE_TRANSFER.getCode().toString());
        }

        //发送审批成功或失败消息各种消息
        noticeApprovalResult.getReceiveUserIds().add(ticketTransferEntity.getCreatorId().toString());
        //给申请人发送消息
        sendMsgService.sendMsgToAllNotifier(ticketTransferEntity.getId(),
                Collections.singletonList(ticketTransferEntity.getCreatorId().toString()), GotoTypeEnum.GOTO_TYPE_TRANSFER.getCode().toString(), msg, user, null);

        baseMapper.updateById(ticketTransferEntity);
        ticketProcessService.updateById(ticketProcessEntity);


    }

    private void cancelTicket(TicketransferEntity ticketTransferEntity) {
        List<String> ticketIds = new ArrayList<>();
        ticketIds.add(ticketTransferEntity.getParentTicketId());
        ticketIds.add(ticketTransferEntity.getTicketId());
        if (StringUtils.isNotBlank(ticketTransferEntity.getTicketRetentionId())) {
            ticketIds.add(ticketTransferEntity.getTicketRetentionId());
        }
        List<TicketEntity> ticketEntities = new ArrayList<>(ticketService.listByIds(ticketIds));
        for (TicketEntity e : ticketEntities) {
            if (e.getId().equals(ticketTransferEntity.getParentTicketId())) {
                e.setInvalidReason(InvalidReasonEnum.TICKET_TRANSFER_FAIL.getCode());
                e.setTicketStatus(TicketStatusEnum.NORMAL_HOLDING.getCode());
                //票据金额
                e.setTicketAvailableAmount(add(e.getTicketAvailableAmount(), ticketTransferEntity.getTransferAmount()));
                //转让中冻结金额
                e.setTransferFrozenAmount(sub(e.getTransferFrozenAmount(), ticketTransferEntity.getTransferAmount()));
            } else {
                e.setInvalidReason(InvalidReasonEnum.TRANSFER_TICKET_CANCEL.getCode());
                e.setTicketStatus(TicketStatusEnum.INVALID.getCode());
            }
        }
        ticketService.updateBatchById(ticketEntities);
    }

    private void saveReviewFailLog(TicketransferEntity ticketTransferEntity, NoticeApprovalResult noticeApprovalResult, User user) {
        List<TicketOperateLogEntity> adds = new ArrayList<>();
        TicketOperateLogEntity ticketOperateLogEntity = ticketOperateLogService.getTicketOperateLogEntity(LogActionTypeEnum.TICKET_TYPE_TRANSFER.getCode(), ticketTransferEntity.getId()
                , TicketLogStatusEnum.TRANSFER_PENDING_REVIEW.getCode(), OperateLogTypeEnum.REVIEW_REJECTION.getCode(), TicketLogStatusEnum.REVIEW_REJECT.getCode(), user
                , noticeApprovalResult.getApprovalRemark(),
                ticketTransferEntity.getReceiveEnterpriseId(), ticketTransferEntity.getReceiveEnterpriseName(),
                ticketTransferEntity.getTransferEnterpriseId(), ticketTransferEntity.getTransferEnterpriseName(), ticketTransferEntity.getTicketId(), "0", null, null,
                noticeApprovalResult);

        TicketOperateLogEntity parentOperateLogEntity = ticketOperateLogService.getTicketOperateLogEntity(LogActionTypeEnum.TICKET_TYPE_TRANSFER.getCode(), ticketTransferEntity.getId()
                , TicketLogStatusEnum.INVALID.getCode(), OperateLogTypeEnum.TRANSFER_ROLLBACK.getCode(), TicketLogStatusEnum.TRANSFER_SUCCESS.getCode(), user
                , noticeApprovalResult.getApprovalRemark(),
                ticketTransferEntity.getReceiveEnterpriseId(), ticketTransferEntity.getReceiveEnterpriseName(),
                ticketTransferEntity.getTransferEnterpriseId(), ticketTransferEntity.getTransferEnterpriseName(), ticketTransferEntity.getParentTicketId(), "0", null, null);

        if (StringUtils.isNotBlank(ticketTransferEntity.getTicketRetentionId())) {
            TicketOperateLogEntity ticketRetentionEntity = ticketOperateLogService.getTicketOperateLogEntity(LogActionTypeEnum.TICKET_TYPE_TRANSFER.getCode(), ticketTransferEntity.getId()
                    , TicketLogStatusEnum.TRANSFER_RETAINED.getCode(), OperateLogTypeEnum.TRANSFER_ROLLBACK.getCode(), TicketLogStatusEnum.INVALID.getCode(), user
                    , noticeApprovalResult.getApprovalRemark(),
                    ticketTransferEntity.getReceiveEnterpriseId(), ticketTransferEntity.getReceiveEnterpriseName(),
                    ticketTransferEntity.getTransferEnterpriseId(), ticketTransferEntity.getTransferEnterpriseName(), ticketTransferEntity.getTicketRetentionId(), "0", null, null);
            adds.add(ticketRetentionEntity);
        }
        adds.add(ticketOperateLogEntity);
        adds.add(parentOperateLogEntity);
        ticketOperateLogService.saveBatch(adds);

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void transferSignInApprovalCallback(NoticeApprovalResult noticeApprovalResult, TicketProcessEntity ticketProcessEntity, User user) throws SysException {
        TicketransferEntity ticketTransferEntity = baseMapper.selectById(ticketProcessEntity.getTicketTransferId());
        ticketTransferEntity.setSignTime(new Date());
        ticketTransferEntity.setSignId(user.getId());
        ticketTransferEntity.setSignRemark(noticeApprovalResult.getApprovalRemark());
        this.setNoticeApprovalResult(noticeApprovalResult, ticketTransferEntity);
        //更新子票和留存票及母票数据
        if (ApproveResultStatusEnum.APPROVE_STATUS_YES.getCode().equals(noticeApprovalResult.getApprovalResult())) {
            //更新转让申请单数据
            ticketTransferEntity.setTicketStatus(TicketStatusEnum.TRANSFER_SUCCESS.getCode());
            this.sendSuccessMessageSign(ticketTransferEntity, noticeApprovalResult, user);

            ticketOperateLogService.saveTicketLog(LogActionTypeEnum.TICKET_TYPE_TRANSFER.getCode(), ticketTransferEntity.getId()
                    , TicketLogStatusEnum.TRANSFER_PENDING_SIGN.getCode(), OperateLogTypeEnum.TRANSFER_SIGN.getCode(), TicketLogStatusEnum.TRANSFER_SUCCESS.getCode(), user
                    , noticeApprovalResult.getApprovalRemark(),
                    ticketTransferEntity.getReceiveEnterpriseId(), ticketTransferEntity.getReceiveEnterpriseName(),
                    ticketTransferEntity.getTransferEnterpriseId(), ticketTransferEntity.getTransferEnterpriseName(), ticketTransferEntity.getTicketId(), "0", null, null
                    , noticeApprovalResult);
            //处理票据流程图
            this.passTransferFlowChart(ticketTransferEntity, user);
        } else {
            ticketTransferEntity.setTicketStatus(TicketStatusEnum.REFUSE.getCode());
            this.sendFailMessageSign(ticketTransferEntity, noticeApprovalResult, user);
            this.saveSignFailLog(ticketTransferEntity, noticeApprovalResult, user);
            //处理票据流程图
            this.cancelTransferFlowChart(ticketTransferEntity, user);
        }
        //处理转让涉及的票状态
        this.changeStatus(ticketTransferEntity, noticeApprovalResult.getApprovalResult(), TicketStatusEnum.NORMAL_HOLDING.getCode(), true);
        this.updateById(ticketTransferEntity);

    }

    private void saveSignFailLog(TicketransferEntity ticketTransferEntity, NoticeApprovalResult noticeApprovalResult, User user) {
        List<TicketOperateLogEntity> adds = new ArrayList<>();
        TicketOperateLogEntity ticketOperateLogEntity = ticketOperateLogService.getTicketOperateLogEntity(LogActionTypeEnum.TICKET_TYPE_TRANSFER.getCode(), ticketTransferEntity.getId()
                , TicketLogStatusEnum.TRANSFER_PENDING_SIGN.getCode(), OperateLogTypeEnum.SIGN_REJECTION.getCode(), TicketLogStatusEnum.REFUSE.getCode(), user
                , noticeApprovalResult.getApprovalRemark(),
                ticketTransferEntity.getReceiveEnterpriseId(), ticketTransferEntity.getReceiveEnterpriseName(),
                ticketTransferEntity.getTransferEnterpriseId(), ticketTransferEntity.getTransferEnterpriseName(), ticketTransferEntity.getTicketId(), "0", null, null
                , noticeApprovalResult);
        TicketOperateLogEntity parentOperateLogEntity = ticketOperateLogService.getTicketOperateLogEntity(LogActionTypeEnum.TICKET_TYPE_TRANSFER.getCode(), ticketTransferEntity.getId()
                , TicketLogStatusEnum.INVALID.getCode(), OperateLogTypeEnum.TRANSFER_ROLLBACK.getCode(), TicketLogStatusEnum.TRANSFER_SUCCESS.getCode(), user
                , noticeApprovalResult.getApprovalRemark(),
                ticketTransferEntity.getReceiveEnterpriseId(), ticketTransferEntity.getReceiveEnterpriseName(),
                ticketTransferEntity.getTransferEnterpriseId(), ticketTransferEntity.getTransferEnterpriseName(), ticketTransferEntity.getParentTicketId(), "0", null, null);

        if (StringUtils.isNotBlank(ticketTransferEntity.getTicketRetentionId())) {
            TicketOperateLogEntity ticketRetentionEntity = ticketOperateLogService.getTicketOperateLogEntity(LogActionTypeEnum.TICKET_TYPE_TRANSFER.getCode(), ticketTransferEntity.getId()
                    , TicketLogStatusEnum.TRANSFER_RETAINED.getCode(), OperateLogTypeEnum.TRANSFER_ROLLBACK.getCode(), TicketLogStatusEnum.INVALID.getCode(), user
                    , noticeApprovalResult.getApprovalRemark(),
                    ticketTransferEntity.getReceiveEnterpriseId(), ticketTransferEntity.getReceiveEnterpriseName(),
                    ticketTransferEntity.getTransferEnterpriseId(), ticketTransferEntity.getTransferEnterpriseName(), ticketTransferEntity.getTicketRetentionId(), "0", null, null);
            adds.add(ticketRetentionEntity);
        }
        adds.add(ticketOperateLogEntity);
        adds.add(parentOperateLogEntity);
        ticketOperateLogService.saveBatch(adds);
    }


    @Override
    public TicketTransferInfo recheckInfo(String id) throws SysException {
        TicketransferEntity ticketransferEntity = this.getById(id);
        //父票id
        TicketEntity parentTicket = ticketService.getById(ticketransferEntity.getParentTicketId());
        TicketTransferInfo ticketTransferInfo = new TicketTransferInfo();
        BeanUtils.copyProperties(ticketransferEntity, ticketTransferInfo);
        ticketTransferInfo.setHandStatusInfo(TicketStatusEnum.getStatusHandInfo(ticketTransferInfo.getTicketStatus()));
        if (TicketStatusEnum.REJECT_LIST.contains(ticketTransferInfo.getTicketStatus())) {
            ticketTransferInfo.setHandStatus("失败");
        } else if (TicketStatusEnum.TRANSFER_IN_LIST.contains(ticketTransferInfo.getTicketStatus())) {
            ticketTransferInfo.setHandStatus("转让中");
        } else if (TicketStatusEnum.SUCCESS_IN_LIST.contains(ticketTransferInfo.getTicketStatus())) {
            ticketTransferInfo.setHandStatus("成功");
        } else if (TicketStatusEnum.CANCEL.getCode().equals(ticketTransferInfo.getTicketStatus())) {
            ticketTransferInfo.setHandStatus("失败");
        }

        String surplusDays = this.calculateSurplusDays(parentTicket.getCashTime(), parentTicket.getTicketStatus());
        ticketTransferInfo.setSurplusCashingDays(surplusDays);
        ticketTransferInfo.setPaymentModeInfo(PaymentModeEnum.getValue(parentTicket.getPaymentMode()));
        // 找到转让相关附件信息
        List<TicketDataEntity> dataEntities = ticketDataService.getByTicketId(id, TicketActionTypeEnum.TICKET_TYPE_TRANSFER.getCode());
        if (!CollectionUtils.isEmpty(dataEntities)) {
            Map<String, List<TicketDataEntity>> map = dataEntities.stream().collect(Collectors.groupingBy(TicketDataEntity::getDataType));
            ticketTransferInfo.setInvoiceList(map.get(DataTypeEnum.INVOICE.getCode()));
            ticketTransferInfo.setProofList(map.get(DataTypeEnum.TICKET.getCode()));
        }
        ticketTransferInfo.setHandProgress(TicketStatusEnum.getProgress(ticketTransferInfo.getTicketStatus()));
        this.getApUserShowInfoList(ticketransferEntity, ticketTransferInfo, ApproveTypeEnum.TRANSFER.getCode());
        return this.setTransferContract(ticketTransferInfo);
    }

    @Override
    public TicketTransferInfo signInfo(String id) throws SysException {
        TicketransferEntity ticketransferEntity = this.getById(id);
        //父票id
        TicketEntity parentTicket = ticketService.getById(ticketransferEntity.getParentTicketId());
        TicketTransferInfo ticketTransferInfo = new TicketTransferInfo();
        BeanUtils.copyProperties(ticketransferEntity, ticketTransferInfo);
        ticketTransferInfo.setHandStatusInfo(TicketStatusEnum.getStatusHandInfo(ticketTransferInfo.getTicketStatus()));
        if (TicketStatusEnum.REJECT_LIST.contains(ticketTransferInfo.getTicketStatus())) {
            ticketTransferInfo.setHandStatus("失败");
        } else if (TicketStatusEnum.TRANSFER_IN_LIST.contains(ticketTransferInfo.getTicketStatus())) {
            ticketTransferInfo.setHandStatus("转让中");
        } else if (TicketStatusEnum.SUCCESS_IN_LIST.contains(ticketTransferInfo.getTicketStatus())) {
            ticketTransferInfo.setHandStatus("成功");
        } else if (TicketStatusEnum.CANCEL.getCode().equals(ticketTransferInfo.getTicketStatus())) {
            ticketTransferInfo.setHandStatus("失败");
        }

        String surplusDays = this.calculateSurplusDays(parentTicket.getCashTime(), parentTicket.getTicketStatus());
        ticketTransferInfo.setSurplusCashingDays(surplusDays);
        ticketTransferInfo.setPaymentModeInfo(PaymentModeEnum.getValue(parentTicket.getPaymentMode()));
        // 找到转让相关附件信息
        List<TicketDataEntity> dataEntities = ticketDataService.getByTicketId(id, TicketActionTypeEnum.TICKET_TYPE_TRANSFER.getCode());
        if (!CollectionUtils.isEmpty(dataEntities)) {
            Map<String, List<TicketDataEntity>> map = dataEntities.stream().collect(Collectors.groupingBy(TicketDataEntity::getDataType));
            ticketTransferInfo.setInvoiceList(map.get(DataTypeEnum.INVOICE.getCode()));
            ticketTransferInfo.setProofList(map.get(DataTypeEnum.TICKET.getCode()));
        }
        ticketTransferInfo.setHandProgress(TicketStatusEnum.getProgress(ticketTransferInfo.getTicketStatus()));
        this.getApUserShowInfoList(ticketransferEntity, ticketTransferInfo, ApproveTypeEnum.SIGN_TRANSFER.getCode());
        return this.setTransferContract(ticketTransferInfo);
    }

    private void getApUserShowInfoList(TicketransferEntity ticketransferEntity, TicketTransferInfo ticketTransferInfo, String approveType) throws SysException {
        QueryWrapper<TicketProcessEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TicketProcessEntity::getApproveType, approveType)
                .eq(TicketProcessEntity::getTicketTransferId, ticketransferEntity.getId());
        TicketProcessEntity one = ticketProcessService.getOne(queryWrapper);
        if (one != null) {
            ticketTransferInfo.setApUserShowInfos(ticketProcessService.getApUserShowInfoList(one));
        }
    }

    /**
     * 发送签收成功消息
     *
     * @param ticketTransferEntity
     * @param noticeApprovalResult
     * @param user
     * @throws SysException
     */
    private void sendSuccessMessageSign(TicketransferEntity ticketTransferEntity, NoticeApprovalResult noticeApprovalResult, User user) throws SysException {
        //发送 复核人-申请人-抄送人
        String msg = MailMessageConstant.SIGN_TICKET_TRANSFER_APPROVE.replace(MailMessageConstant.TICKET_REPLACE_SIGN, ticketTransferEntity.getReceiveEnterpriseName())
                .replace("{{金额}}", NumberUtil.numberFormatString(ticketTransferEntity.getTransferAmount()));
        //发送 平台审核人员
        String platMsg = MailMessageConstant.TICKET_TRANSFER_SIGN_PASS_MSG.replace(MailMessageConstant.TICKET_REPLACE_SIGN, ticketTransferEntity.getReceiveEnterpriseName())
                .replace("{{金额}}", NumberUtil.numberFormatString(ticketTransferEntity.getTransferAmount())
                        .replace("{{转让方}}", ticketTransferEntity.getTransferEnterpriseName()));
        //todo 获取平台签收权限的管理员ids
        List<String> platIds = new ArrayList<>();
        sendMsgService.sendMsgToAllNotifier(ticketTransferEntity.getTicketId(), noticeApprovalResult.getBeforeReceiveUserIds()
                , GotoTypeEnum.GOTO_TYPE_SIGN_TRANSFER.getCode().toString(), msg, user, null);
        sendMsgService.sendMsgToAllNotifier(ticketTransferEntity.getTicketId(), platIds
                , GotoTypeEnum.GOTO_TYPE_SIGN_TRANSFER.getCode().toString(), platMsg, user, null);
    }


    /**
     * 发送供应商拒收消息
     *
     * @param ticketTransferEntity
     * @param noticeApprovalResult
     * @param user
     * @throws SysException
     */
    private void sendFailMessageSign(TicketransferEntity ticketTransferEntity, NoticeApprovalResult noticeApprovalResult, User user) throws SysException {
        //发送 复核人-申请人-抄送人
        String msg = MailMessageConstant.TICKET_TRANSFER_SIGN_FAIL_MSG.replace("{{签收方}}", ticketTransferEntity.getReceiveEnterpriseName())
                .replace("{{金额}}", NumberUtil.numberFormatString(ticketTransferEntity.getTransferAmount()));
        //发送 平台审核人员
        String platMsg = MailMessageConstant.TICKET_TRANSFER_SIGN_PLAT_FAIL_MSG.replace("{{签收方}}", ticketTransferEntity.getReceiveEnterpriseName())
                .replace("{{金额}}", NumberUtil.numberFormatString(ticketTransferEntity.getTransferAmount())
                        .replace("{{转让方}}", ticketTransferEntity.getTransferEnterpriseName()));
        //todo 获取平台签收权限的管理员ids
        List<String> platIds = new ArrayList<>();
        sendMsgService.sendMsgToAllNotifier(ticketTransferEntity.getTicketId(), noticeApprovalResult.getBeforeReceiveUserIds()
                , GotoTypeEnum.GOTO_TYPE_SIGN_TRANSFER.getCode().toString(), msg, user, null);
        sendMsgService.sendMsgToAllNotifier(ticketTransferEntity.getTicketId(), platIds
                , GotoTypeEnum.GOTO_TYPE_SIGN_TRANSFER.getCode().toString(), platMsg, user, null);
    }

    /**
     * 转让签收审批人处理
     *
     * @param ticketransferEntity 转让申请
     * @return userDto       用户信息
     * @throws SysException 业务异常
     */
    private void setNoticeApprovalResult(NoticeApprovalResult noticeApprovalResult, TicketransferEntity ticketransferEntity) throws SysException {
        //1 查询开立签收对应的开立流程
        QueryWrapper<TicketProcessEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().in(TicketProcessEntity::getApproveType, Arrays.asList(ApproveTypeEnum.SIGN_OPEN_TRANSFER.getCode(),
                ApproveTypeEnum.TRANSFER.getCode()))
                .eq(TicketProcessEntity::getTicketTransferId, ticketransferEntity.getId());
        List<TicketProcessEntity> list = ticketProcessService.list(queryWrapper);
        if (!CollectionUtils.isEmpty(list)) {
            //2 调用rpc，开立签收审核结束后，查询开立的所有审核人id集合
            List<String> collect = list.stream().map(TicketProcessEntity::getApproveId).collect(Collectors.toList());
            List<String> userIds = processFeign.getAllUserByApprovalId(new StringIds(collect));
            noticeApprovalResult.setBeforeReceiveUserIds(userIds);
        }
    }
}